#include <rtthread.h>

//二手闲置,丢了可惜送人算了
#define RT_USING_DEVICE

#ifdef  RT_USING_DEVICE
/**
 * This function registers a device driver with specified name
 * 
 * @param dev the pointer of device driver structure
 * @param name the device driver's name  //器件驱动器的名字
 * @param flags the flag of device       //有实力的安静
 * 
 * @return the error code ,RT_EOK on initialization successfully 
 */
rt_err_t rt_device_register(rt_device_t dev,const char *name,rt_uint16_t flags)
{
    if(dev==RT_NULL)
    {
        return -RT_ERROR;
    }

    if(rt_device_find(name) != RT_NULL)  //发现后就不会,在初始化了
    {   //这个发现函数得结合设置函数来理解      发现类型  然后发现名字
        return -RT_ERROR;
    }
    rt_object_init(&(dev->parent),RT_Object_CLass_Device,name); //type name copy 然后将object挂载在上面
    dev->flag=flags;
    dev->ref_count=0;
    dev->open_flag=0;

#if defined(RT_USING_POSIX)
    dev->fops=RT_NULL;
    rt_list_init(&(dev->wait_queue));
#endif

    return RT_EOK;
}
RTM_EXPORT(rt_device_register);

/**
 * @brief This function removes a previously registered device driver
 * 
 * @param dev the pointer of device driver structure
 * 
 * @return the error code, RT_EOK on successfully 
 */
rt_err_t rt_device_unregister(rt_device_t dev)
{
    RT_ASSERT(dev != RT_NULL);

    rt_object_detach( &(dev->parent) );  //将object从链表上移除

    return RT_EOK;
}
RTM_EXPORT(rt_device_unregister);




// /**
//  * The information of the kernel object
//  */
// struct rt_object_information
// {
//     enum rt_object_class_type type;                 /*object class type*/
//     rt_list_t                 object_list;          /*object list*/
//     rt_size_t                 object_size;          /*object size*/
// };
/**
 * This function finds a device driver by specified name
 * 
 * @param name the device driver's name
 * 
 * @return the registered device driver on successful or RT_NULL on failure
 */
rt_device_t rt_device_find(const char *name)
{
    struct rt_object *object;
    struct rt_list_node *node;  //双向链表指针
    struct rt_object_information *information;

    /*enter critical*/
    if(rt_thread_self() != RT_NULL)
    {   //当前线程存在
        rt_enter_critical();      //开调度锁,不调度
    }
    /*try to find device object*/  //这里只是找一个数组
    information=rt_object_get_information(RT_Object_Class_Device);  //找到类型为RT_Object_Class_Device类型的元素,并返回其地址
    RT_ASSERT(information != RT_NULL);  //当information为空时会发生断言

    for(node =information->object_list.next;node != &(information->object_list);node=node->next)
    {   //如果object_list双向链表为空的话那么object_list.next就会指向object_list
        //上面就是对双向链表进行遍历
        object=rt_list_entry(node,struct rt_object,list);  //后面还得看一看

        if(rt_strncmp(object->name,name,RT_NAME_MAX)==0)
        {   //找到了名字为name的object
            /*level critical*/
            if(rt_thread_self() != RT_NULL)
            {   //当前线程存在
                rt_exit_critical();  //开启调度器
            }       //故这里的object放在rt_device_t  结构体定义的头部
            return (rt_device_t)object;  //强制转换一下  //实际应该是挂载的rt_device
        }
    }
    //到了这一步说明没有找到所谓的目标device
    /*leave critical*/
    if(rt_thread_self() != RT_NULL)
    {   //    rt_current_thread = RT_NULL;刚开始时会有这个玩意儿
        rt_exit_critical();  //开启调度器
    }

    /*not found*/
    return RT_NULL;
}
RTM_EXPORT(rt_device_find);


#ifdef  RT_USING_HEAP
/**
 * @brief This function creates a device object with user data size
 *   //防
 * @param type ,the kind type of this device object
 * @param attach_size , the size of user data
 * 
 * @return the allocated device object ,or RT_NULL when failed 
 */
rt_device_t rt_device_create(int type,int attach_size)
{
    int size;

    rt_device_t device;

    size=RT_ALIGN(sizeof(struct rt_device) ,RT_ALIGN_SIZE);  //向上4bytes对齐
    size += attach_size;   //加上额外的大小??

    device = (rt_device_t)rt_malloc(size);
    if(device)
    {   //如果device创造成功
        rt_memset(device,0x0,sizeof(struct rt_device));
        device->type= (enum rt_device_class_type)type;
    }

    return device;
}
RTM_EXPORT(rt_device_create);

/**
 * @brief This function destroy the specific device object.  //剥离,然后释放内存
 * 
 * @param device ,the specific device object
 */
void rt_device_destroy(rt_device_t device)
{
    /*unregister device firstly*/
    rt_device_unregister(device);  //将device这个对象从  rt_object_container上面剥离

    /*release this device object*/
    rt_free(device);   //这里是一个地址值
}
RTM_EXPORT(rt_device_destroy);
#endif

//不饿，，东西难吃 ，，监控你

/**
 * @brief This function will initialize the specified device
 * 
 * @param dev the pointer of device driver structure
 * @param the result
 */
rt_err_t rt_device_init(rt_device_t dev)
{
    rt_err_t result=RT_EOK;

    RT_ASSERT(dev != RT_NULL);

    /*get device init handler*/
    if(dev->init != RT_NULL)
    {   //init函数存在
        if( !(dev->flag & RT_DEVICE_FLAG_ACTIVATED) )
        {   //当前device处于非活跃状态   
            result=dev->init(dev);   //还没活跃,那我们就给他init
            if(result != RT_EOK)
            { //初始化错误
                rt_kprintf("to initialize device:%s failed . The error code is %d\n",
                            dev->parent.name,result);
            }
            else
            {   //初始化成功
                dev->flag |= RT_DEVICE_FLAG_ACTIVATED; //将其标注为活跃状态
            }
        }
    }

    return result;
}


/**
 * This function will open a device
 * 
 * @param dev the pointer of device driver structure (器件驱动结构体指针)
 * @param oflag the flags for device open
 * 
 * @return the result
 */
rt_err_t rt_device_open(rt_device_t dev,rt_uint16_t oflag)
{
    rt_err_t result=RT_EOK;

    RT_ASSERT(dev != RT_NULL);

    /*if device is not initialized , initialize it*/
    if( !(dev->flag & RT_DEVICE_FLAG_ACTIVATED) )
    {   //器件还未被激活
        if(dev->init !=RT_NULL)
        {   //调用器件初始化函数
            result=dev->init(dev);
            if(result != RT_EOK)
            {                                                                       //object.name    结果                                            
                rt_kprintf("To initialize device:%s failed .The error code is %d\n",dev->parent.name,result);
                return result;
            }
        }
        dev->flag |= RT_DEVICE_FLAG_ACTIVATED;   //标记已经被激活
    }

    /*device is a stand alone device and opened*/
    if( (dev->flag & RT_DEVICE_FLAG_STANDALONE) &&  (dev->open_flag & RT_DEVICE_OFLAG_OPEN) )
    {
        return -RT_EBUSY;
    }

    /*call device open interface*/
    if(dev->open != RT_NULL)
    {   //上面是初始化,这里是打开   open函数存在
        result=dev->open(dev,oflag);
    }
    else
    {       //open函数不存在
        dev->open_flag=(oflag & RT_DEVICE_OFLAG_MASK);
    }

    /*set open flag*/
    if(result==RT_EOK || result == -RT_ENOSYS)
    {   //这里应该是打开成功了
        dev->open_flag |=RT_DEVICE_OFLAG_OPEN;

        dev->ref_count++;           //器件关闭时是减减
        /**
         * don't let bad things happen silently . If you are bitten by this assert,
         * please set the ref_count to a bigger type
         */
        RT_ASSERT(dev->ref_count != 0); 
    }
    result result;
}
RTM_EXPORT(rt_device_open);

/**
 * This function will close a device
 *
 * @param dev the pointer of device driver structure
 *
 * @return the result
 */
rt_err_t rt_device_close(rt_device_t dev)
{
    rt_err_t result = RT_EOK;

    RT_ASSERT(dev != RT_NULL);

    if (dev->ref_count == 0)
        return -RT_ERROR;

    dev->ref_count--;

    if (dev->ref_count != 0)
    {   //这里是什么意思???  按理说,到这里是ref_count应该是为0的
        return RT_EOK;
    }
    //此时ref_count是0
    /* call device close interface */
    if (dev->close != RT_NULL)
    {
        result = dev->close(dev);
    }

    /* set open flag */
    if (result == RT_EOK || result == -RT_ENOSYS)
    {
        dev->open_flag = RT_DEVICE_OFLAG_CLOSE;
    }

    return result;
}
RTM_EXPORT(rt_device_close);

//值几个钱儿,脚踏实地

/**
 *  This function will read some data from a device
 *  
 * @param dev the pointer of device driver structure
 * @param pos the position of reading 
 * @param buffer the data buffer to save read data
 * @param size the size of buffer
 * 
 * @return the actually read size on successful,otherwise negative returned.
 * 
 * @note since 0.4.0 ,the unit of size/pos is a block for block device
 */
rt_size_t rt_device_read(rt_device_t dev,rt_off_t pos,void *buffer,rt_size_t size)
{
    RT_ASSERT(dev != RT_NULL);     

    if(dev->ref_count ==0)   //当器件被打开后,ref_count不为0
    {   //此时,器件没有被打开,故得设置错误码
        rt_set_errno(-RT_ERROR);  //可以通过rt_get_errno函数来获得
        return 0;   
    }
    //这玩意儿的本质是啥？？？,请你一定要搞清楚不然大部分人都会上套
    /*call device read interface*/
    if(dev->read !=RT_NULL)
    {
        return dev->read(dev,pos,buffer,size);  //关于device这部分,还是得将底层研究一下
    }
    //到这一步说明,dev->read是空的,RT_NULL
    /*set error code*/
    rt_set_errno(-RT_ENOSYS);  //no system 没有系统

    return 0;
}
RTM_EXPORT(rt_device_read);

/**
 * This function will write some data to a device
 * 
 * @param dev the pointer of device driver structure
 * @param pos the position of written
 * @param buffer the data buffer to be written to device
 * @param size the size of buffer
 * 
 * @return the actually written size on successful,otherwise negative returned
 * 
 * @note since 0.4.0, the unit of size/pos is a block for block device.
 */
rt_size_t rt_device_write(rt_device_t dev,rt_off_t pos,const void *buffer,rt_size_t size)
{
    RT_ASSERT(dev != RT_NULL);

    if(dev->ref_count==0)
    {   //此时,器件没有被打开,故得设置错误码
        rt_set_errno(-RT_ERROR);  //可以通过rt_get_errno函数来获得
        //中断嵌套  和  当前线程
        return 0;   
    }

    /*call device write interface*/
    if(dev->write != RT_NULL)
    {
        return dev->write(dev,pos,buffer,size);
    }

    /*set error code*/
    rt_set_errno(-RT_ENOSYS);  //no system 没有系统
    return 0;
}
RTM_EXPORT(rt_device_write);

//一切从简

/**
 * This function will perform a variety of control functions on devices.
 * 
 * @param dev the pointer of device driver structure
 * @param cmd the cmmand sent to device
 * @param arg the argument of command
 * 
 * @return the result
 */
rt_err_t rt_device_control(rt_device_t dev,int cmd,void * arg)
{
    RT_ASSERT(dev != RT_NULL);

    /*call device control interface*/
    if(dev->control != RT_NULL)
    {
        return dev->control(dev,cmd,arg);
    }
    //底层未实现
    return -RT_ENOSYS;   //直接返回,不用设置变量
}
RTM_EXPORT(rt_device_control);

//结合实例来看一看

/**
 * This function will set the reception indication callback function .
 * This callback function is invoked when this device receives data
 * 
 * @param dev the pointer of device driver structure
 * @param rx_ind the indication callback function
 * 
 * @return RT_EOK
 */
rt_err_t rt_device_set_rx_indicate(rt_device_t dev,rt_err_t (*rx_ind)(rt_device_t dev,rt_size_t size))
{                                                //   这里是一个函数指针
    RT_ASSERT(dev != RT_NULL);
                              //接受指示回调函数
    dev->rx_indicate=rx_ind;  //指定一个函数指针

    return RT_EOK;
}
RTM_EXPORT(rt_device_set_rx_indicate);

/**
 * This function will set the indication callback function when device has
 * written data to physical hardware.
 * 
 * @param dev the pointer of device driver structure
 * @param tx_done the indication callback function    //指示回调函数
 * 
 * @return RT_EOK
 */
rt_err_t rt_device_set_tx_complete(rt_device_t dev,rt_err_t (*tx_done)(rt_device_t dev,void *buffer))
{
    RT_ASSERT(dev != RT_NULL);

    dev->tx_complete=tx_done;

    return RT_EOK;
}
RTM_EXPORT(rt_device_set_tx_complete);

#endif